#include "imgui/FileDialog.h"

using namespace ImGui;

FileDialog::FileDialog(const std::string& path)
{
    m_Path = fs::absolute(fs::path(path)).string();
    LoadChild();


}

void FileDialog::HandleFunc()
{
    if (m_ShouldChanged)
    {
        m_Path = m_NewPath;
        LoadChild();
        m_ShouldChanged = false;
    }
    if (m_ShouldBack)
    {

        SendSignal(fs::absolute(fs::path(m_Path)).parent_path().string());
        m_ShouldBack = false;
    }
}

void FileDialog::ViewFunc()
{

    m_Editor.Edit<std::string>("Path ", m_Path);
    m_Editor.Edit<std::string>("FileName ", m_TargetFilename);

    if (ImGui::Button("open"))
    {
        SendSignal(m_Path);
    }
    ImGui::SameLine();

    if (ImGui::Button("submit"))
    {
        std::cout << "on submit" << std::endl;
        m_OnSubmit = true;

    }
    ImGui::SameLine();


    m_ShouldBack |= ImGui::Button("back");

    for (const auto& it : m_PathLabels)
    {
        std::string filename = it.m_FileName.c_str();
        if (filename.empty())
        {
            filename = it.m_Path;
        }
        bool btnClicked = ImGui::Button(filename.c_str());
        if (btnClicked)
        {
            SendSignal(it.m_Path);
        }
        ImGui::SameLine();

    }
    ImGui::Text("%s", "");

    bool doubleClicked = false;
    bool itemClicked = false;
    if (ImGui::BeginTable("FileTable", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg))
    {
        ImGui::TableSetupColumn("File Name");
        ImGui::TableSetupColumn("Update Time");
        ImGui::TableSetupColumn("File Size");

        ImGui::TableHeadersRow();
        ImGui::PushButtonRepeat(true);
        for (int row = 0; row < m_FileLabels.size(); ++row)
        {
            auto& fileLabel = m_FileLabels[row];
            ImGui::PushID(&fileLabel);

            ImGui::TableNextRow();

            bool isSelected = (row == m_SelectRow);
            ImVec4 rowBgColor = isSelected ? ImVec4(0.2f, 0.4f, 0.8f, 1.0f) : ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
            ImU32 rowBgColorU32 = ImGui::ColorConvertFloat4ToU32(rowBgColor);

            ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, rowBgColorU32);

            ImGui::TableSetColumnIndex(0);
            //bool selectable = ImGui::Selectable(m_FileLabels[row].m_FileName.c_str(), false, ImGuiSelectableFlags_SpanAllColumns);
            bool selectable = ImGui::Button(m_FileLabels[row].m_FileName.c_str());

            if (selectable)
            {
                m_SelectRow = row; 

            }
            itemClicked |= ImGui::IsItemClicked();
            doubleClicked |= ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left);

            // Update Time 
            ImGui::TableSetColumnIndex(1);
            ImGui::Text("%s", fileLabel.m_UpdateTime.c_str());

            // File Size 
            ImGui::TableSetColumnIndex(2);
            ImGui::Text("%llu", fileLabel.m_FileSize);

            ImGui::PopID();


        }
        ImGui::PopButtonRepeat();


        ImGui::EndTable();
    }

    if (doubleClicked && itemClicked)
    {
        auto label = m_FileLabels[m_SelectRow];
        std::cout << "double clicked " << label.m_FileName << std::endl;
        if (label.isDir)
        {
            SendSignal(m_FileLabels[m_SelectRow].m_Path);
        }
        else
        {
            m_TargetFilename = label.m_FileName;
            this->m_OnSubmit = true;
        }

    }


    if (ImGui::IsWindowFocused())
    {
        m_ShouldBack |= ImGui::IsMouseClicked(3);
    }

}



void FileDialog::LoadChild()
{

    m_PathLabels.clear();

    fs::path p1(fs::absolute(m_Path));

    fs::path currentPath;
    for (const auto& part : p1) {
        // Build the path incrementally
        currentPath /= part;
        if (!currentPath.string().empty())
        {
            PathLabel inst;
            inst.m_FileName = currentPath.filename().string();
            inst.m_Path = currentPath.string();
            m_PathLabels.push_back(inst);
        }
    }
    m_PathLabels[0].m_FileName = "[./]";
    m_PathLabels[0].m_Path = "./";

    m_FileLabels.clear();
    for (const auto& it : fs::directory_iterator(m_Path))
    {
        bool isDir = fs::is_directory(it.path());;
        //if (isDir)
        {
            FileLabel label;
            label.m_FileName = it.path().filename().string();
            label.m_Path = it.path().string();
            if(isDir)
            {
                label.m_FileSize = 0;
            }
            else
            {
                label.m_FileSize = fs::file_size(it.path());
            }

            label.m_UpdateTime = GetLastUpdateTime(it.path().string());
            label.isDir = isDir;
            m_FileLabels.push_back(label);
        }

    }
    // Sort in descending order
    std::sort(m_FileLabels.begin(), m_FileLabels.end(), [](FileLabel a, FileLabel b) {
        return a.isDir > b.isDir;
        });


}

std::string FileDialog::GetLastUpdateTime(const std::string& path)
{
    auto ftime = std::filesystem::last_write_time(path);
    auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
        ftime - decltype(ftime)::clock::now() + std::chrono::system_clock::now());
    std::time_t cftime = std::chrono::system_clock::to_time_t(sctp);

    std::stringstream ss;
    ss << std::put_time(std::localtime(&cftime), "%F %T");

    return ss.str();
}

bool FileDialog::IsRoot(const fs::path& p)
{
    return p.has_root_name() && p.has_root_directory();
}

std::string FileDialog::GetFullPath()
{
    fs::path p = fs::path(m_Path) / fs::path(m_TargetFilename);
    return p.string();

}

void FileDialog::SendSignal(const std::string& path)
{
    fs::path p1(path);

    if (fs::is_directory(path) && fs::exists(path))
    {

        m_NewPath = path;
        m_ShouldChanged = true;
    }
}
